<?php
//https://packagist.org/packages/amphp/parallel
require '../vendor/autoload.php';

use Amp\Future;
use Amp\Parallel\Worker;
use function Amp\async;
use Amp\Cancellation;
use Amp\Parallel\Worker\Task;
use Amp\Sync\Channel;

class FetchTask implements Task
{
    private $url;

    public function __construct($url)
    {
        $this->url = $url;
    }

    public function run(Channel $channel, Cancellation $cancellation): mixed
    {
        return file_get_contents($this->url); // Example blocking function
    }
}

$urls = [
    'http://127.0.0.1:9501/test/slow_api?r=1',
    'http://127.0.0.1:9501/test/slow_api?r=2',
    'http://127.0.0.1:9501/test/slow_api?r=3',
    'http://127.0.0.1:9501/test/slow_api?r=4',
    'http://127.0.0.1:9501/test/slow_api?r=5',
    'http://127.0.0.1:9501/test/slow_api?r=6',
    'http://127.0.0.1:9501/test/slow_api?r=7',
    'http://127.0.0.1:9501/test/slow_api?r=8',
    'http://127.0.0.1:9501/test/slow_api?r=9',
    'http://127.0.0.1:9501/test/slow_api?r=10',
];

$executions = [];
foreach ($urls as $url) {
    // FetchTask is just an example, you'll have to implement
    // the Task interface for your task.
    $executions[$url] = Worker\submit(new FetchTask($url));
}

// Each submission returns an Execution instance to allow two-way
// communication with a task. Here we're only interested in the
// task result, so we use the Future from Execution::getFuture()
$responses = Future\await(array_map(
    function (Worker\Execution $e) {
        return $e->getFuture();
    },
    $executions
));

foreach ($responses as $url => $response) {
    \printf("Read %d bytes from %s\n", \strlen($response), $url);
}